package zju.ccnt.fileserverProxy.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import zju.ccnt.fileserverProxy.repository.FileServerRepository;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * Created by zha on 14/11/27.
 */
@Component(value = "leastUsedFileServerLoadBalance")
public class LeastUsedFileServerLoadBalance implements FileServerLoadBalance {

    private final static int DEFAULT_RANGE_SIZE = 20;

    FileServerRepository fileServerRepository;

    @Autowired
    public LeastUsedFileServerLoadBalance(FileServerRepository fileServerRepository){
        this.fileServerRepository = fileServerRepository;
    }

    @Override
    public String selectFileServer(int size) {
        int tailStart = -1;
        String address = null;
        long serverCount = fileServerRepository.countFileServer();
        while (address == null && tailStart + serverCount > 0){
            List<Map<String, String>> candidates = getCandidates(tailStart);
            for (Map<String, String> fileServer : candidates){
                int capacity = Integer.parseInt(fileServer.get("capacity"));
                int used = Integer.parseInt(fileServer.get("size"));
                String serverName = fileServer.get("name");

                if (capacity - used > size){
                    fileServerRepository.removeFileServer(serverName);
                    fileServerRepository.leftPush(serverName);
                    address = fileServer.get("postUrl");
                }
            }
            tailStart -= LeastUsedFileServerLoadBalance.DEFAULT_RANGE_SIZE;
        }
        return address;
    }

    private List<Map<String, String>> getCandidates(int start){
        List<String> serverNames = fileServerRepository.getFileServersFromTail(start, LeastUsedFileServerLoadBalance.DEFAULT_RANGE_SIZE);
        List<Map<String, String>> servers = new ArrayList<Map<String, String>>();
        for (String serverName: serverNames){
            servers.add(fileServerRepository.getFileServerDetail(serverName));
        }
        return servers;
    }

}
